/*****************************************************************************
*
*  PROJECT:		
*               
*  LICENSE:		
*
*  DEVELOPER:	
*
*****************************************************************************/

#include "EonSkybox.h"

void Eon::Skybox::render( Eon::Camera camera )
{
	glDisable( GL_DEPTH_TEST );

	glPushMatrix();

		glRotatef( camera.getRotation().getY(), 0.0f, 1.0f, 0.0f );			// Rotating the skybox with the camera on the y axis

		glEnable( GL_TEXTURE_CUBE_MAP_EXT );
		glBindTexture( GL_TEXTURE_CUBE_MAP_EXT, cubeMap );

		glBegin( GL_TRIANGLE_STRIP );

			//west
			glTexCoord3f(-TEX_COORD, -TEX_COORD , TEX_COORD );
			glVertex3f(-SKY_DISTANCE, -SKY_DISTANCE,  SKY_DISTANCE );
			glTexCoord3f(-TEX_COORD, TEX_COORD, TEX_COORD );
			glVertex3f(-SKY_DISTANCE, SKY_DISTANCE,  SKY_DISTANCE );
			glTexCoord3f(-TEX_COORD, -TEX_COORD, -TEX_COORD );
			glVertex3f(-SKY_DISTANCE, -SKY_DISTANCE, -SKY_DISTANCE );
			glTexCoord3f(-TEX_COORD, TEX_COORD,-TEX_COORD );
			glVertex3f(-SKY_DISTANCE, SKY_DISTANCE,  -SKY_DISTANCE );

			//north
			glTexCoord3f(TEX_COORD, -TEX_COORD,-TEX_COORD );
			glVertex3f(SKY_DISTANCE, -SKY_DISTANCE, -SKY_DISTANCE );
			glTexCoord3f(TEX_COORD, TEX_COORD,-TEX_COORD );
			glVertex3f(SKY_DISTANCE, SKY_DISTANCE, -SKY_DISTANCE );	

			//east
			glTexCoord3f( TEX_COORD, -TEX_COORD, TEX_COORD );
			glVertex3f( SKY_DISTANCE, -SKY_DISTANCE,  SKY_DISTANCE );
			glTexCoord3f( TEX_COORD, TEX_COORD, TEX_COORD );
			glVertex3f( SKY_DISTANCE, SKY_DISTANCE,  SKY_DISTANCE );

			//south
			glTexCoord3f( -TEX_COORD, -TEX_COORD, TEX_COORD );
			glVertex3f( -SKY_DISTANCE, -SKY_DISTANCE,  SKY_DISTANCE );
			glTexCoord3f( -TEX_COORD, TEX_COORD, TEX_COORD );
			glVertex3f( -SKY_DISTANCE, SKY_DISTANCE,  SKY_DISTANCE );

		glEnd();

		glBegin(GL_QUADS);	

			//up
			glTexCoord3f( -TEX_COORD, TEX_COORD, -TEX_COORD );
			glVertex3f( -SKY_DISTANCE, SKY_DISTANCE,  -SKY_DISTANCE );
			glTexCoord3f( -TEX_COORD, TEX_COORD, TEX_COORD );
			glVertex3f( -SKY_DISTANCE, SKY_DISTANCE,  SKY_DISTANCE );
			glTexCoord3f( TEX_COORD, TEX_COORD, TEX_COORD );
			glVertex3f( SKY_DISTANCE, SKY_DISTANCE,  SKY_DISTANCE );
			glTexCoord3f( TEX_COORD, TEX_COORD, -TEX_COORD );
			glVertex3f( SKY_DISTANCE, SKY_DISTANCE,  -SKY_DISTANCE );

			//down
			glTexCoord3f( TEX_COORD, -TEX_COORD, -TEX_COORD );
			glVertex3f( SKY_DISTANCE, -SKY_DISTANCE,  -SKY_DISTANCE );
			glTexCoord3f( TEX_COORD, -TEX_COORD, TEX_COORD );
			glVertex3f( SKY_DISTANCE, -SKY_DISTANCE,  SKY_DISTANCE );
			glTexCoord3f( -TEX_COORD, -TEX_COORD, TEX_COORD );
			glVertex3f( -SKY_DISTANCE, -SKY_DISTANCE,  SKY_DISTANCE );
			glTexCoord3f( -TEX_COORD, -TEX_COORD, -TEX_COORD );
			glVertex3f( -SKY_DISTANCE, -SKY_DISTANCE,  -SKY_DISTANCE );

		glEnd();

	glPopMatrix();

	glEnable( GL_DEPTH_TEST );
	glDisable( GL_TEXTURE_CUBE_MAP_EXT );
}

int Eon::Skybox::init()
{
	// create gluint array and set the GL properties for top, bottom and the four sides
	static GLuint cubeFaces[6] = {
    GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT,
    GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT,
    GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT,
    GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT,
    GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT,
    GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT
	};

	// now load the cube map
	glEnable( GL_TEXTURE_CUBE_MAP_EXT );
	glGenTextures( 1, &cubeMap );			// create the cubemap texture on gluint cubeMap

	// Sanity check for loading the textures and confirming they are correctly loaded
	glBindTexture( GL_TEXTURE_CUBE_MAP_EXT, cubeMap );
	bool success = true;
	if ( !loadFace( cubeFaces[0],"textures/xpos.bmp" ) )
		success =  false;
	if ( !loadFace( cubeFaces[1],"textures/xneg.bmp" ) )
		success =  false;
	if ( !loadFace( cubeFaces[2],"textures/ypos.bmp" ) )
		success =  false;
	if ( !loadFace( cubeFaces[3],"textures/yneg.bmp" ) )
		success =  false;
	if ( !loadFace( cubeFaces[4],"textures/zpos.bmp" ) )
		success =  false;
	if ( !loadFace( cubeFaces[5],"textures/zneg.bmp" ) )
		success = false;

	if ( !success )
	{
		MessageBox( NULL, "Cannot load Cube textures,", "Texture not found!", MB_OK );
		return success;
	}

	glTexParameteri( GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glEnable( GL_TEXTURE_CUBE_MAP_EXT );

	// updateTexgen
	glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT );
	glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT );
	glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT );

	// updateWrap
	glTexParameteri( GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
	glTexParameteri( GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
	glTexParameteri( GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE );

	glDisable( GL_TEXTURE_CUBE_MAP_EXT );
	return TRUE;
}

bool Eon::Skybox::loadFace(GLenum target, char *filename)
{
	// Load the skybox faces
	HBITMAP hBMP;														// Handle Of The Bitmap
	BITMAP	BMP;														// Bitmap Structure
	hBMP = (HBITMAP)LoadImage(GetModuleHandle( NULL ), filename, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE );

	GetObject(hBMP, sizeof(BMP), &BMP);									// Get The Object
																		// hBMP:        Handle To Graphics Object
																		// sizeof(BMP): Size Of Buffer For Object Information
																		// &BMP:        Buffer For Object Information

	glPixelStorei(GL_UNPACK_ALIGNMENT, 4);								// Pixel Storage Mode (Word Alignment / 4 Bytes)
	
	glTexImage2D(target, 0, 3, BMP.bmWidth, BMP.bmHeight, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits);

	DeleteObject(hBMP);													// Delete The Object

	return true;
}

GLuint Eon::Skybox::getCubeMapTexture( void )
{
	return cubeMap;
}